package com.b2c.ftysys.helper;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;

public class ObjectUtils {

	/**
	 * 得到某个对象的公共属性
	 * 
	 * @param owner
	 *            , fieldName
	 * @return 该属性对象
	 * @throws Exception
	 * 
	 */
	public Object getProperty(Object owner, String fieldName) throws Exception {
		Class<?> ownerClass = owner.getClass();

		Field field = ownerClass.getField(fieldName);

		Object property = field.get(owner);

		return property;
	}

	/**
	 * 得到某类的静态公共属性
	 * 
	 * @param className
	 *            类名
	 * @param fieldName
	 *            属性名
	 * @return 该属性对象
	 * @throws Exception
	 */
	public Object getStaticProperty(String className, String fieldName)
			throws Exception {
		Class<?> ownerClass = Class.forName(className);

		Field field = ownerClass.getField(fieldName);

		Object property = field.get(ownerClass);

		return property;
	}

	/**
	 * 执行某对象方法
	 * 
	 * @param owner
	 *            对象
	 * @param methodName
	 *            方法名
	 * @param args
	 *            参数
	 * @return 方法返回值
	 * @throws Exception
	 */
	public static Object invokeMethod(Object owner, String methodName,
			Object[] args) throws Exception {

		Class<?> ownerClass = owner.getClass();

		Class<?>[] argsClass = new Class[args.length];

		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}

		Method method = ownerClass.getMethod(methodName, argsClass);

		return method.invoke(owner, args);
	}

	public static Object invokeMethod(Object owner, String methodName)
			throws Exception {

		Class<?> ownerClass = owner.getClass();

		Method method = ownerClass.getMethod(methodName);

		return method.invoke(owner);
	}

	/**
	 * 执行某类的静态方法
	 * 
	 * @param className
	 *            类名
	 * @param methodName
	 *            方法名
	 * @param args
	 *            参数数组
	 * @return 执行方法返回的结果
	 * @throws Exception
	 */
	public Object invokeStaticMethod(String className, String methodName,
			Object[] args) throws Exception {
		Class<?> ownerClass = Class.forName(className);

		Class<?>[] argsClass = new Class[args.length];

		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}

		Method method = ownerClass.getMethod(methodName, argsClass);

		return method.invoke(null, args);
	}

	/**
	 * 新建实例
	 * 
	 * @param className
	 *            类名
	 * @param args
	 *            构造函数的参数
	 * @return 新建的实例
	 * @throws Exception
	 */
	public Object newInstance(String className, Object[] args) throws Exception {
		Class<?> newoneClass = Class.forName(className);

		Class<?>[] argsClass = new Class[args.length];

		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}

		Constructor<?> cons = newoneClass.getConstructor(argsClass);

		return cons.newInstance(args);

	}

	/**
	 * 是不是某个类的实例
	 * 
	 * @param obj
	 *            实例
	 * @param cls
	 *            类
	 * @return 如果 obj 是此类的实例，则返回 true
	 */
	public boolean isInstance(Object obj, Class<?> cls) {
		return cls.isInstance(obj);
	}

	/**
	 * 得到数组中的某个元素
	 * 
	 * @param array
	 *            数组
	 * @param index
	 *            索引
	 * @return 返回指定数组对象中索引组件的值
	 */
	public Object getByArray(Object array, int index) {
		return Array.get(array, index);
	}

	/**
	 * 将xxx_yyy转化为xxxYyy格式
	 * 
	 * @param str
	 *            需要转化的字符,需包含‘_’下划线
	 * @return
	 */
	private static String getFormtName(String str) {
		StringBuffer reutnStr = new StringBuffer("");
		if (str != null) {
			if (str.indexOf("_") <= 0)
				return str.toLowerCase();
			String regEx = "_(?=[a-z])";// 正则表达式 匹配_+字母
			String strTemp = str.toLowerCase();
			Pattern p = Pattern.compile(regEx);
			Matcher m = p.matcher(strTemp);
			boolean result1 = m.find();
			int sign = 0;
			while (result1) { // 进行匹配
				reutnStr.append(strTemp.substring(sign, m.start()));
				reutnStr.append(strTemp.substring(m.end(), m.end() + 1)
						.toUpperCase());
				sign = m.end() + 1;
				result1 = m.find();
			}
			reutnStr.append(strTemp.substring(sign));
		} else
			return null;

		String returnStr = reutnStr.toString();

		// 首字母转化为大写
		return returnStr.replaceFirst(returnStr.substring(0, 1), returnStr
				.substring(0, 1).toUpperCase());
	}

	/**
	 * 根据获取的URL参数,生成VO
	 * 
	 * @param dataMap
	 * @return
	 * @throws IllegalAccessException
	 * @throws InstantiationException
	 */
	@SuppressWarnings("rawtypes")
	public static Object ConvertURLRequsetMapToObj(Map dataMap, Class<?> clazz)
			throws InstantiationException, IllegalAccessException {
		Object obj = clazz.newInstance();
		if (null == dataMap)
			return obj;
		for (Object key : dataMap.keySet()) {
			if (key instanceof String) {
				String[] values;
				if (dataMap.get(key) instanceof String[]) {
					values = (String[]) dataMap.get(key);
				} else
					continue;
				if (values == null || values.length <= 0)
					continue;

				Method[] ms = clazz.getDeclaredMethods();
				for (Method m : ms) {
					if (m.getName().indexOf("set") != 0)
						continue;
					if (("set" + key).toLowerCase().equals(
							m.getName().toLowerCase())) {
						if (m.getParameterTypes() == null
								|| m.getParameterTypes().length != 1)
							continue;
						Object arg = null;
						try {// 只处理Integer型、Long型及String型
							if (m.getParameterTypes()[0] == java.lang.Integer.class) {
								arg = Integer.parseInt(values[0]);
							} else if (m.getParameterTypes()[0] == java.lang.Long.class) {
								arg = Long.parseLong(values[0]);
							} else if (m.getParameterTypes()[0] == java.lang.String.class) {
								arg = values[0];
							} else
								continue;
							Object[] args = { arg };
							invokeMethod(obj, m.getName(), args);
						} catch (ClassCastException e) {
							e.printStackTrace();
						} catch (java.lang.NumberFormatException ex) {
							ex.printStackTrace();
						} catch (InstantiationException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
		return obj;
	}

	public static Object mapToObj(Map<String, Object> dataMap, Class<?> clazz)
			throws Exception {
		Object data = clazz.newInstance();
		for (String key : dataMap.keySet()) {
			if (dataMap.get(key) == null)
				continue;
			String mapMethod = getFormtName(key);
			Method[] items = clazz.getDeclaredMethods();
			for (Method item : items) {
				String methodName = item.getName();
				if (("set" + mapMethod).toLowerCase().equals(
						item.getName().toLowerCase())) {
					Class<?> paramClazz = item.getParameterTypes()[0];
					Object[] args = { 1 };
					if (dataMap.get(key) != null
							|| !StringUtils.isEmpty(String.valueOf(dataMap
									.get(key)))) {
						try {
							if (dataMap.get(key) instanceof java.sql.Timestamp) {
								java.sql.Timestamp date = (java.sql.Timestamp) dataMap
										.get(key);
								Date cDate = new Date();
								cDate.setTime(date.getTime());
								args[0] = cDate;
							} else if (dataMap.get(key) instanceof java.sql.Date
									&& paramClazz.isInstance(new Date())) {
								java.sql.Date date = (java.sql.Date) dataMap
										.get(key);
								Date cDate = new Date();
								cDate.setTime(date.getTime());
								args[0] = cDate;
							} else if (!(dataMap.get(key) instanceof Date)
									&& paramClazz.equals(Date.class)) {
								args[0] = DateUtils.parseToDate(
										String.valueOf(dataMap.get(key)),
										DateUtils.yyyyMMdd);
							} else if ((dataMap.get(key) instanceof Date)
									&& paramClazz.equals(String.class)) {
								args[0] = DateUtils.parseToString(
										(Date) dataMap.get(key),
										DateUtils.yyyyMMdd);
							} else if (paramClazz.equals(String.class)) {
								args[0] = String.valueOf(dataMap.get(key));
							} else if (dataMap.get(key) instanceof java.math.BigDecimal
									&& paramClazz.isInstance(new Long(0))) {
								args[0] = (new BigDecimal(
										(Long) dataMap.get(key))).longValue();
							} else if (dataMap.get(key) instanceof java.math.BigDecimal
									&& paramClazz.isInstance(new Integer(0))) {
								args[0] = (new BigDecimal(
										(Integer) dataMap.get(key))).intValue();
							} else if (dataMap.get(key) instanceof java.math.BigDecimal
									&& paramClazz.isInstance(new Double(0))) {
								args[0] = (new BigDecimal(
										(Double) dataMap.get(key)))
										.doubleValue();
							} else if (dataMap.get(key) instanceof java.math.BigDecimal
									&& paramClazz
											.isInstance(new java.lang.Short(
													(short) 0))) {
								args[0] = (new BigDecimal(
										(Short) dataMap.get(key))).shortValue();
							} else if (paramClazz.isInstance(dataMap.get(key))) {
								args[0] = paramClazz.cast(dataMap.get(key));
							} else if (dataMap.get(key) instanceof Double
									&& paramClazz.isInstance(new BigDecimal(0))) {
								args[0] = (new BigDecimal(
										(Double) dataMap.get(key)));
							} else if (dataMap.get(key) instanceof Double
									&& paramClazz.isInstance(new Integer(0))) {
								args[0] = ((Double) dataMap.get(key))
										.intValue();
							} else if (dataMap.get(key) instanceof Long
									&& paramClazz.isInstance(new Integer(0))) {
								args[0] = ((Long) dataMap.get(key)).intValue();
							} else {
								args[0] = (String) dataMap.get(key);
							}
						} catch (Exception e) {
							e.printStackTrace();
							System.out.println("[" + key + "]"
									+ dataMap.get(key) + "("
									+ dataMap.get(key).getClass() + ")"
									+ " can not set in method " + methodName
									+ " ( " + paramClazz + " ) ");
						}
						try {
							invokeMethod(data, methodName, args);
						} catch (Exception e) {
							e.printStackTrace();
							System.out.println("[" + key + "]"
									+ dataMap.get(key) + "("
									+ dataMap.get(key).getClass() + ")"
									+ " can not set in method " + methodName
									+ " ( " + paramClazz + " ) ");
						}
					}
				}
			}
		}
		return data;
	}

	public static Object objToObj(Object obj, Class<?> clazz) throws Exception {
		if (obj == null)
			return clazz.newInstance();
		Object retunObj = clazz.newInstance();
		Method[] ms = clazz.getMethods();
		Method[] finderMs = obj.getClass().getDeclaredMethods();
		for (Method m : ms) {
			if (m.getName().indexOf("set") != 0)
				continue;
			String proName = m.getName().substring(3);
			for (Method finderM : finderMs) {
				if (finderM.getName().indexOf("get") != 0)
					continue;
				if (("get" + proName).equals(finderM.getName())) {
					if (invokeMethod(obj, finderM.getName()) != null) {
						Object[] args = { invokeMethod(obj, finderM.getName()) };
						invokeMethod(retunObj, m.getName(), args);
					}
				}
			}
		}
		return retunObj;
	}

	public static String getOrderBy(String column, int aCode) throws Exception {
		String str = "";
		if (column == null || column.trim().length() <= 0)
			throw new Exception("排序列名不能为空!");

		char first = column.charAt(0);// 第一个字母不能为大写字母
		if (first >= 'A' && first <= 'Z')
			throw new Exception("首字母不能为大写");

		column = column.replaceAll("(?=[A-Z])", "_");
		if (column.indexOf("_") <= 0)
			throw new Exception();

		if (aCode == 0)
			str = " " + column + "  DESC ";
		else {
			str = " " + column + "  ";
		}

		return str;
	}

	public static void main(String[] args) {
		try {
			System.out.println(ObjectUtils.getOrderBy("guideSeq", 1));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
